import { set, merge,get } from 'lodash-es';
import { isNullOrUnDef, isArray, isNullOrEmpty } from './index';

type ChartPropName<T extends string, K extends string> = `chart${CamelName<T>}${CamelName<K>}`;
/**
 * ChartPropName使用示例
 * type xxxChartPropName = ChartPropName<'radar' | 'pie', 'gridType' | 'gridColor'>;
 * const enum RadarExtraKey {
 *   GridTypeCc = 'gridType.cc',
 *   GridColor = 'gridColor',
 * }
 *
 * type RadarChartPropName = ChartPropName<'radar', keyof typeof RadarExtraKey>;
 */

// 扩展配置中的图表属性
const getExtraChartAttrs = (props:any): Record<ChartType, ExtraChartType> => {
  return {
    pie: new CovertExtraPie(props).init(), // 饼图
    column: new CovertExtraColumn(props).init(), // 条形图
    gauge: new CovertExtraGauge(props).init(), // 仪表盘
    radar: new CovertExtraRadar(props).init(), //雷达图
    bar: new CovertExtraBar(props).init(), // 柱状图
    line: new CovertExtraLine(props).init(), // 折线图
    word: new CovertExtraWord(props).init(), //词云图
    mix: new CovertExtraMix(props).init(), //混合图
    funnel: new CovertExtraFunnel(props).init(), //漏斗图
  };
};

// 图表配置数据
export class CovertOptions {
  private readonly valueMap: any;
  private readonly type: ChartType;
  constructor(valueMap: any, type: ChartType) {
    this.valueMap = valueMap;
    this.type = type;
  }
  init() {
    // 扩展配置信息
    const extraData = merge(
      {},
      new CovertExtraChart(this.valueMap, this.type ).init(),
      new CovertTooltip(this.valueMap).init(),
      new CovertMarkLine(this.valueMap).init(),
    );
    return Object.assign(
      {},
      extraData,
      new CovertChartBase(this.valueMap).init(),
      new CovertTitle(this.valueMap).init(),
      new CovertXAxis(this.valueMap).init(),
      new CovertYAxis(this.valueMap).init(),
      new CovertLegend(this.valueMap).init(),
    );
  }
}

// 图表扩展配置
export class CovertExtraChart {
  private readonly valueMap: any;
  private readonly type: ChartType;
  private readonly keyChainList: any;
  private extraChartOptions: any;
  constructor(valueMap: any, type: ChartType) {
    this.valueMap = valueMap;
    this.type = type;
    this.extraChartOptions = {} as any;
    this.keyChainList = {
      column: 'extra.column',
      mount: 'extra.mount',
      bar: 'extra.bar',
      line: 'extra.line',
      area: 'extra.area',
      scatter: 'extra.scatter',
      bubble: 'extra.bubble',
      mix: 'extra.mix',
      pie: 'extra.pie',
      ring: 'extra.ring',
      rose: 'extra.rose',
      radar: 'extra.radar',
      arcbar: 'extra.arcbar',
      gauge: 'extra.gauge',
      funnel: 'extra.funnel',
      word: 'extra.word',
      candle: 'extra.candle',
      map: 'extra.map',
    };
  }

  init() {
    set(
      this.extraChartOptions,
      this.keyChainList[this.type],
      getExtraChartAttrs(this.valueMap)[this.type],
    );
    return this.extraChartOptions;
  }
}

// 漏斗图扩展属性枚举
const enum FunnelExtraKey {
  Type = 'type',
  ActiveOpacity = 'activeOpacity',
  ActiveWidth = 'activeWidth',
  Border = 'border',
  BorderWidth = 'borderWidth',
  BorderColor = 'borderColor',
  FillOpacity = 'fillOpacity',
  MinSize = 'minSize',
  LabelAlign = 'labelAlign',
  LinearType = 'linearType',
  CustomColor = 'customColor',
}
type FunnelChartPropName = ChartPropName<'funnel', keyof typeof FunnelExtraKey>;
// 漏斗图扩展配置
export class CovertExtraFunnel {
  private readonly valueMap: Record<FunnelChartPropName, any>;
  private readonly keyChainList: Record<FunnelChartPropName, FunnelExtraKey>;
  private options: ExtraChartType;
  private keyList: FunnelChartPropName[];
  constructor(valueMap: Record<FunnelChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartFunnelType: FunnelExtraKey.Type,
      chartFunnelActiveOpacity: FunnelExtraKey.ActiveOpacity,
      chartFunnelActiveWidth: FunnelExtraKey.ActiveWidth,
      chartFunnelBorder: FunnelExtraKey.Border,
      chartFunnelBorderWidth: FunnelExtraKey.BorderWidth,
      chartFunnelBorderColor: FunnelExtraKey.BorderColor,
      chartFunnelFillOpacity: FunnelExtraKey.FillOpacity,
      chartFunnelLabelAlign: FunnelExtraKey.LabelAlign,
      chartFunnelLinearType: FunnelExtraKey.LinearType,
      chartFunnelCustomColor: FunnelExtraKey.CustomColor,
      chartFunnelMinSize: FunnelExtraKey.MinSize,
    };
    this.keyList = Object.keys(this.keyChainList) as FunnelChartPropName[];
  }

  init() {
    this.keyList.map((key: FunnelChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}

// 混合图扩展属性枚举
const enum MixExtraKey {
  ColumnWidth = 'column.width',
  ColumnSeriesGap = 'column.seriesGap',
  ColumnBarBorderCircle = 'column.barBorderCircle',
  ColumnBarBorderRadius = 'column.barBorderRadius',
  ColumnLinearType = 'column.linearType',
  ColumnLinearOpacity = 'column.linearOpacity',
  ColumnCustomColor = 'column.customColor',
  ColumnColorStop = 'column.colorStop',
  AreaGradient = 'area.gradient',
  AreaOpacity = 'area.opacity',
}
type MixChartPropName = ChartPropName<'mix', keyof typeof MixExtraKey>;
// 混合图扩展配置
export class CovertExtraMix {
  private readonly valueMap: Record<MixChartPropName, any>;
  private readonly keyChainList: Record<MixChartPropName, MixExtraKey>;
  private options: MixExtsPropsType;
  private keyList: MixChartPropName[];
  constructor(valueMap: Record<MixChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartMixColumnWidth: MixExtraKey.ColumnWidth,
      chartMixColumnSeriesGap: MixExtraKey.ColumnSeriesGap,
      chartMixColumnBarBorderCircle: MixExtraKey.ColumnBarBorderCircle,
      chartMixColumnBarBorderRadius: MixExtraKey.ColumnBarBorderRadius,
      chartMixColumnLinearType: MixExtraKey.ColumnLinearType,
      chartMixColumnLinearOpacity: MixExtraKey.ColumnLinearOpacity,
      chartMixColumnCustomColor: MixExtraKey.ColumnCustomColor,
      chartMixColumnColorStop: MixExtraKey.ColumnColorStop,
      chartMixAreaGradient: MixExtraKey.AreaGradient,
      chartMixAreaOpacity: MixExtraKey.AreaOpacity,
    };
    this.keyList = Object.keys(this.keyChainList) as MixChartPropName[];
  }

  init() {
    this.keyList.map((key: MixChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}
// 饼状图扩展属性枚举
const enum PieExtraKey {
  ActiveOpacity = 'activeOpacity',
  ActiveRadius = 'activeRadius',
  OffsetAngle = 'offsetAngle',
  LabelWidth = 'labelWidth',
  CustomRadius = 'customRadius',
  Border = 'border',
  BorderWidth = 'borderWidth',
  BorderColor = 'borderColor',
  LinearType = 'linearType',
  CustomColor = 'customColor',
}
type PieChartPropName = ChartPropName<'pie', PieExtraKey>;
// 饼状图扩展配置
export class CovertExtraPie {
  private readonly valueMap: Record<PieChartPropName, any>;
  private readonly keyChainList: Record<PieChartPropName, PieExtraKey>;
  private options: PartialRecord<PieExtraKey, any>;
  private keyList: PieChartPropName[];
  constructor(valueMap: Record<PieChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartPieActiveOpacity: PieExtraKey.ActiveOpacity,
      chartPieActiveRadius: PieExtraKey.ActiveRadius,
      chartPieOffsetAngle: PieExtraKey.OffsetAngle,
      chartPieLabelWidth: PieExtraKey.LabelWidth,
      chartPieCustomRadius: PieExtraKey.CustomRadius,
      chartPieBorder: PieExtraKey.Border,
      chartPieBorderWidth: PieExtraKey.BorderWidth,
      chartPieBorderColor: PieExtraKey.BorderColor,
      chartPieLinearType: PieExtraKey.LinearType,
      chartPieCustomColor: PieExtraKey.CustomColor,
    };
    this.keyList = Object.keys(this.keyChainList) as PieChartPropName[];
  }

  init() {
    this.keyList.map((key: PieChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}
// 雷达图扩展属性枚举
const enum RadarExtraKey {
  GridType = 'gridType',
  GridColor = 'gridColor',
  GridCount = 'gridCount',
  GridEval = 'gridEval',
  AxisLabel = 'axisLabel',
  AxisLabelTofix = 'axisLabelTofix',
  LabelColor = 'labelColor',
  LabelPointShow = 'labelPointShow',
  LabelPointRadius = 'labelPointRadius',
  LabelPointColor = 'labelPointColor',
  Opacity = 'opacity',
  Border = 'border',
  BorderWidth = 'borderWidth',
  LinearType = 'linearType',
  CustomColor = 'customColor',
  Max = 'max',
}

type RadarChartPropName = ChartPropName<'radar', keyof typeof RadarExtraKey>;
// 雷达图扩展配置
export class CovertExtraRadar {
  private readonly valueMap: Record<RadarChartPropName, any>;
  private readonly keyChainMap: Record<RadarChartPropName, RadarExtraKey>;
  private options: PartialRecord<RadarExtraKey, any>;
  private keyList: RadarChartPropName[];
  constructor(valueMap: Record<RadarChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainMap = {
      chartRadarGridType: RadarExtraKey.GridType,
      chartRadarGridColor: RadarExtraKey.GridColor,
      chartRadarGridCount: RadarExtraKey.GridCount,
      chartRadarGridEval: RadarExtraKey.GridEval,
      chartRadarAxisLabel: RadarExtraKey.AxisLabel,
      chartRadarAxisLabelTofix: RadarExtraKey.AxisLabelTofix,
      chartRadarLabelColor: RadarExtraKey.LabelColor,
      chartRadarLabelPointShow: RadarExtraKey.LabelPointShow,
      chartRadarLabelPointRadius: RadarExtraKey.LabelPointRadius,
      chartRadarLabelPointColor: RadarExtraKey.LabelPointColor,
      chartRadarOpacity: RadarExtraKey.Opacity,
      chartRadarBorder: RadarExtraKey.Border,
      chartRadarBorderWidth: RadarExtraKey.BorderWidth,
      chartRadarLinearType: RadarExtraKey.LinearType,
      chartRadarCustomColor: RadarExtraKey.CustomColor,
      chartRadarMax: RadarExtraKey.Max,
    };
    this.keyList = Object.keys(this.keyChainMap) as RadarChartPropName[];
  }

  init() {
    this.keyList.map((key: RadarChartPropName) => {
      const keyChain = this.keyChainMap[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}

// 折线图扩展属性枚举
const enum LineExtraKey {
  Type = 'type',
  Width = 'width',
}
type LineChartPropName = ChartPropName<'line', LineExtraKey>;
// 折线图扩展配置
export class CovertExtraLine {
  private readonly valueMap: Record<LineChartPropName, any>;
  private readonly keyChainList: Record<LineChartPropName, LineExtraKey>;
  private options: PartialRecord<LineExtraKey, any>;
  private keyList: LineChartPropName[];
  constructor(valueMap: Record<LineChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartLineType: LineExtraKey.Type,
      chartLineWidth: LineExtraKey.Width,
    };
    this.keyList = Object.keys(this.keyChainList) as LineChartPropName[];
  }

  init() {
    this.keyList.map((key: LineChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}

// 柱状图扩展属性枚举
const enum BarExtraKey {
  Type = 'type',
  Width = 'width',
  SeriesGap = 'seriesGap',
  CategoryGap = 'categoryGap',
  BarBorderCircle = 'barBorderCircle',
  BarBorderRadius = 'barBorderRadius',
  LinearType = 'linearType',
  LinearOpacity = 'linearOpacity',
  CustomColor = 'customColor',
  ColorStop = 'colorStop',
  MeterBorder = 'meterBorder',
  MeterFillColor = 'meterFillColor',
  ActiveBgColor = 'activeBgColor',
  ActiveBgOpacity = 'activeBgOpacity',
}
type BarChartPropName = ChartPropName<'bar', BarExtraKey>;
// 柱状图扩展配置
export class CovertExtraBar {
  private readonly valueMap: Record<BarChartPropName, any>;
  private readonly keyChainList: Record<BarChartPropName, BarExtraKey>;
  private options: PartialRecord<BarExtraKey, any>;
  private keyList: BarChartPropName[];
  constructor(valueMap: Record<BarChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartBarType: BarExtraKey.Type,
      chartBarWidth: BarExtraKey.Width,
      chartBarSeriesGap: BarExtraKey.SeriesGap,
      chartBarCategoryGap: BarExtraKey.CategoryGap,
      chartBarBarBorderCircle: BarExtraKey.BarBorderCircle,
      chartBarBarBorderRadius: BarExtraKey.BarBorderRadius,
      chartBarLinearType: BarExtraKey.LinearType,
      chartBarLinearOpacity: BarExtraKey.LinearOpacity,
      chartBarCustomColor: BarExtraKey.CustomColor,
      chartBarColorStop: BarExtraKey.ColorStop,
      chartBarMeterBorder: BarExtraKey.MeterBorder,
      chartBarMeterFillColor: BarExtraKey.MeterFillColor,
      chartBarActiveBgColor: BarExtraKey.ActiveBgColor,
      chartBarActiveBgOpacity: BarExtraKey.ActiveBgOpacity,
    };
    this.keyList = Object.keys(this.keyChainList) as BarChartPropName[];
  }

  init() {
    this.keyList.map((key: BarChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}


// 柱状图扩展属性枚举
const enum ColumnExtraKey {
  Type = 'type',
  Width = 'width',
  SeriesGap = 'seriesGap',
  CategoryGap = 'categoryGap',
  BarBorderCircle = 'barBorderCircle',
  BarBorderRadius = 'barBorderRadius',
  LinearType = 'linearType',
  LinearOpacity = 'linearOpacity',
  CustomColor = 'customColor',
  ColorStop = 'colorStop',
  MeterBorder = 'meterBorder',
  MeterFillColor = 'meterFillColor',
  ActiveBgColor = 'activeBgColor',
  ActiveBgOpacity = 'activeBgOpacity',
}
type ColumnChartPropName = ChartPropName<'column', ColumnExtraKey>;
// 柱状图扩展配置
export class CovertExtraColumn {
  private readonly valueMap: Record<ColumnChartPropName, any>;
  private readonly keyChainList: Record<ColumnChartPropName, ColumnExtraKey>;
  private options: PartialRecord<ColumnExtraKey, any>;
  private keyList: ColumnChartPropName[];
  constructor(valueMap: Record<ColumnChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartColumnType: ColumnExtraKey.Type,
      chartColumnWidth: ColumnExtraKey.Width,
      chartColumnSeriesGap: ColumnExtraKey.SeriesGap,
      chartColumnCategoryGap: ColumnExtraKey.CategoryGap,
      chartColumnBarBorderCircle: ColumnExtraKey.BarBorderCircle,
      chartColumnBarBorderRadius: ColumnExtraKey.BarBorderRadius,
      chartColumnLinearType: ColumnExtraKey.LinearType,
      chartColumnLinearOpacity: ColumnExtraKey.LinearOpacity,
      chartColumnCustomColor: ColumnExtraKey.CustomColor,
      chartColumnColorStop: ColumnExtraKey.ColorStop,
      chartColumnMeterBorder: ColumnExtraKey.MeterBorder,
      chartColumnMeterFillColor: ColumnExtraKey.MeterFillColor,
      chartColumnActiveBgColor: ColumnExtraKey.ActiveBgColor,
      chartColumnActiveBgOpacity: ColumnExtraKey.ActiveBgOpacity,
    };
    this.keyList = Object.keys(this.keyChainList) as ColumnChartPropName[];
  }

  init() {
    this.keyList.map((key: ColumnChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}
// 仪表盘扩展属性枚举
const enum GaugeExtraKey {
  Type = 'type',
  Width = 'width',
  LabelColor = 'labelColor',
  LabelOffset = 'labelOffset',
  StartAngle = 'startAngle',
  EndAngle = 'endAngle',
  StartNumber = 'startNumber',
  EndNumber = 'endNumber',
  SplitLineFixRadius = 'splitLine.fixRadius',
  SplitLineSplitNumber = 'splitLine.splitNumber',
  SplitLineWidth = 'splitLine.width',
  SplitLineColor = 'splitLine.color',
  SplitLineChildNumber = 'splitLine.childNumber',
  SplitLineChildWidth = 'splitLine.childWidth',
  PointerWidth = 'pointer.width',
  PointerColor = 'pointer.color',
}
type GaugeChartPropName = ChartPropName<'gauge', keyof typeof GaugeExtraKey>;
// 仪表盘扩展配置
export class CovertExtraGauge {
  private readonly valueMap: Record<GaugeChartPropName, any>;
  private readonly keyChainList: Record<GaugeChartPropName, GaugeExtraKey>;
  private options: PartialRecord<GaugeExtraKey, any>;
  private keyList: GaugeChartPropName[];
  constructor(valueMap: Record<GaugeChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartGaugeType: GaugeExtraKey.Type,
      chartGaugeWidth: GaugeExtraKey.Width,
      chartGaugeLabelColor: GaugeExtraKey.LabelColor,
      chartGaugeLabelOffset: GaugeExtraKey.LabelOffset,
      chartGaugeStartAngle: GaugeExtraKey.StartAngle,
      chartGaugeEndAngle: GaugeExtraKey.EndAngle,
      chartGaugeStartNumber: GaugeExtraKey.StartNumber,
      chartGaugeEndNumber: GaugeExtraKey.EndNumber,
      chartGaugeSplitLineFixRadius: GaugeExtraKey.SplitLineFixRadius,
      chartGaugeSplitLineSplitNumber: GaugeExtraKey.SplitLineSplitNumber,
      chartGaugeSplitLineWidth: GaugeExtraKey.SplitLineWidth,
      chartGaugeSplitLineColor: GaugeExtraKey.SplitLineColor,
      chartGaugeSplitLineChildNumber: GaugeExtraKey.SplitLineChildNumber,
      chartGaugeSplitLineChildWidth: GaugeExtraKey.SplitLineChildWidth,
      chartGaugePointerWidth: GaugeExtraKey.PointerWidth,
      chartGaugePointerColor: GaugeExtraKey.PointerColor,
    };
    this.keyList = Object.keys(this.keyChainList) as GaugeChartPropName[];
  }

  init() {
    this.keyList.map((key: GaugeChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}

// 词云图扩展属性枚举
const enum WordExtraKey {
  Type = 'type',
  AutoColors = 'autoColors',
}
type WordChartPropName = ChartPropName<'word', keyof typeof WordExtraKey>;
// 词云图扩展配置
export class CovertExtraWord {
  private readonly valueMap: Record<WordChartPropName, any>;
  private readonly keyChainList: Record<WordChartPropName, WordExtraKey>;
  private options: PartialRecord<WordExtraKey, any>;
  private keyList: WordChartPropName[];
  constructor(valueMap: Record<WordChartPropName, any>) {
    this.valueMap = valueMap;
    this.options = {};
    this.keyChainList = {
      chartWordType: WordExtraKey.Type,
      chartWordAutoColors: WordExtraKey.AutoColors,
    };
    this.keyList = Object.keys(this.keyChainList) as WordChartPropName[];
  }

  init() {
    this.keyList.map((key: WordChartPropName) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}

// 图表通用配置
export class CovertChartBase {
  private readonly valueMap: any;
  private readonly keyChainList: any;
  private options: any;
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.options = {} as any;
    this.keyChainList = {
      chartBaseColor: 'color',
      chartBasePadding: 'padding',
      chartBaseFontSize: 'fontSize',
      chartBaseFontColor: 'fontColor',
      chartBaseDataLabel: 'dataLabel',
      chartBaseDataPointShape: 'dataPointShape',
      chartBaseDataPointShapeType: 'dataPointShapeType',
      chartBaseEnableScroll: 'enableScroll',
      chartBaseEnableMarkLine: 'enableMarkLine',
      chartBaseCanvas2d: 'canvas2d',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.options, keyChain, this.valueMap[key]);
    });
    return this.options;
  }
}
// 标题
export class CovertTitle {
  private titleValueMap: any;
  private readonly keyChainList: any;
  private title: {};
  private keyList: string[];
  constructor(titleValueMap: any) {
    this.titleValueMap = titleValueMap;
    this.title = {};
    this.keyChainList = {
      chartTitleName: 'title.name',
      chartTitleFontSize: 'title.fontSize',
      chartTitleColor: 'title.color',
      chartTitleOffsetX: 'title.offsetX',
      chartTitleOffsetY: 'title.offsetY',
      chartSubTitleName: 'subtitle.name',
      chartSubTitleFontSize: 'subtitle.fontSize',
      chartSubTitleColor: 'subtitle.color',
      chartSubTitleOffsetX: 'subtitle.offsetX',
      chartSubTitleOffsetY: 'subtitle.offsetY',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.titleValueMap[key]) && set(this.title, keyChain, this.titleValueMap[key]);
    });
    return this.title;
  }
}
// X轴
export class CovertXAxis {
  private valueMap: any;
  private readonly keyChainList: any;
  private xAxis: {};
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.xAxis = {};
    this.keyChainList = {
      chartXAxisDisabled: 'xAxis.disabled',
      chartXAxisAxisLine: 'xAxis.axisLine',
      chartXAxisAxisLineColor: 'xAxis.axisLineColor',
      chartXAxisCalibration: 'xAxis.calibration',
      chartXAxisFontColor: 'xAxis.fontColor',
      chartXAxisFontSize: 'xAxis.fontSize',
      chartXAxisRotateLabel: 'xAxis.rotateLabel',
      chartXAxisRotateAngle: 'xAxis.rotateAngle',
      chartXAxisBoundaryGap: 'xAxis.boundaryGap',
      chartXAxisDisableGrid: 'xAxis.disableGrid',
      chartXAxisGridColor: 'xAxis.gridColor',
      chartXAxisGridType: 'xAxis.gridType',
      chartXAxisScrollShow: 'xAxis.scrollShow',
      chartXAxisItemCount: 'xAxis.itemCount',
    };
    this.keyList = Object.keys(this.keyChainList);
  }
  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.xAxis, keyChain, this.valueMap[key]);
    });
    return this.xAxis;
  }
}
// Y轴
export class CovertYAxis {
  private valueMap: any;
  private readonly keyChainList: any;
  private yAxis: any;
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.yAxis = {};
    this.keyChainList = {
      chartYAxisDisabled: 'yAxis.disabled',
      chartYAxisDisableGrid: 'yAxis.disableGrid',
      chartYAxisGridColor: 'yAxis.gridColor',
      chartYAxisGridType: 'yAxis.gridType',
      chartYAxisSplitNumber: 'yAxis.splitNumber',
      chartYAxisPadding: 'yAxis.padding',
      chartYAxisShowTitle: 'yAxis.showTitle',
      // Y轴-折线/曲线/区域
      chartYAxisLineDisabled: 'yAxis.data[0].disabled',
      chartYAxisLinePosition: 'yAxis.data[0].position',
      chartYAxisLineTitle: 'yAxis.data[0].title',
      chartYAxisLineMin: 'yAxis.data[0].min',
      chartYAxisLineMax: 'yAxis.data[0].max',
      // Y轴-柱子
      chartYAxisColumnDisabled: 'yAxis.data[1].disabled',
      chartYAxisColumnPosition: 'yAxis.data[1].position',
      chartYAxisColumnTitle: 'yAxis.data[1].title',
      chartYAxisColumnMin: 'yAxis.data[1].min',
      chartYAxisColumnMax: 'yAxis.data[1].max',
      // Y轴-点
      chartYAxisPointDisabled: 'yAxis.data[2].disabled',
      chartYAxisPointPosition: 'yAxis.data[2].position',
      chartYAxisPointTitle: 'yAxis.data[2].title',
      chartYAxisPointMin: 'yAxis.data[2].min',
      chartYAxisPointMax: 'yAxis.data[2].max',
    };
    this.keyList = Object.keys(this.keyChainList);
  }
  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.yAxis, keyChain, this.valueMap[key]);
    });
    return this.yAxis;
  }
}
// 图例
export class CovertLegend {
  private readonly valueMap: any;
  private readonly keyChainList: any;
  private legend: {};
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.legend = {};
    this.keyChainList = {
      chartLegendShow: 'legend.show',
      chartLegendPosition: 'legend.position',
      chartLegendFloat: 'legend.float',
      chartLegendPadding: 'legend.padding',
      chartLegendMargin: 'legend.margin',
      chartLegendBackgroundColor: 'legend.backgroundColor',
      chartLegendBorderColor: 'legend.borderColor',
      chartLegendBorderWidth: 'legend.borderWidth',
      chartLegendFontSize: 'legend.fontSize',
      chartLegendFontColor: 'legend.fontColor',
      chartLegendLineHeight: 'legend.lineHeight',
      chartLegendHiddenColor: 'legend.hiddenColor',
      chartLegendItemGap: 'legend.itemGap',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.legend, keyChain, this.valueMap[key]);
    });
    return this.legend;
  }
}
// 提示
export class CovertTooltip {
  private readonly valueMap: any;
  private readonly keyChainList: any;
  private tooltip: any;
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.tooltip = {} as any;
    this.keyChainList = {
      chartTooltipShowBox: 'extra.tooltip.showBox',
      chartTooltipShowCategory: 'extra.tooltip.showCategory',
      chartTooltipBorderRadius: 'extra.tooltip.borderRadius',
      chartTooltipBgColor: 'extra.tooltip.bgColor',
      chartTooltipBgOpacity: 'extra.tooltip.bgOpacity',
      chartTooltipFontColor: 'extra.tooltip.fontColor',
      chartTooltipSplitLine: 'extra.tooltip.splitLine',
      chartTooltipHorizentalLine: 'extra.tooltip.horizentalLine',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.tooltip, keyChain, this.valueMap[key]);
    });
    return this.tooltip;
  }
}
// 标记线
export class CovertMarkLine {
  private readonly valueMap: any;
  private readonly keyChainList: any;
  private markLine: any;
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.markLine = {} as any;
    this.keyChainList = {
      chartMarkLineType: 'extra.markLine.type',
      chartMarkLineDashLength: 'extra.markLine.dashLength',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) && set(this.markLine, keyChain, this.valueMap[key]);
    });
    // 设置复杂类型数据
    set(this.markLine, 'extra.markLine.data', new CovertMarkLineData(this.valueMap).init());
    return this.markLine;
  }
}

// 标记线数据
export class CovertMarkLineData {
  private readonly valueMap: any;
  private readonly keyChainList: any;
  private markLineData: any;
  private markLineDataItem: any;
  private keyList: string[];
  constructor(valueMap: any) {
    this.valueMap = valueMap;
    this.markLineData = [] as any;
    this.markLineDataItem = {} as any;
    this.keyChainList = {
      chartMarkLineColor: 'lineColor',
      chartMarkLineShowLabel: 'showLabel',
      chartMarkLineLabelAlign: 'labelAlign',
      chartMarkLineLabelOffsetX: 'labelOffsetX',
      chartMarkLineLabelOffsetY: 'labelOffsetY',
      chartMarkLineLabelFontColor: 'labelFontColor',
      chartMarkLineLabelBgColor: 'labelBgColor',
      chartMarkLineLabelBgOpacity: 'labelBgOpacity',
    };
    this.keyList = Object.keys(this.keyChainList);
  }

  init() {
    this.keyList.map((key) => {
      const keyChain = this.keyChainList[key];
      !isNullOrUnDef(this.valueMap[key]) &&
        set(this.markLineDataItem, keyChain, this.valueMap[key]);
    });
    this.valueMap['chartMarkLineData'] &&
      this.valueMap['chartMarkLineData'].map((item: any) => {
        this.markLineData.push({ ...item, ...this.markLineDataItem });
      });
    return this.markLineData;
  }
}

// 移动端图表数据源转换
export const getChartsDataSourceConvert = (conditionDependencyMap, type, list, convert, conditionConfig, propsDefined) => {
  if (!type || !list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 将条件格式转换成key的map
  const conditionConfigMap = {};
  if (conditionConfig) {
    conditionConfig.forEach((item) => {
      if (conditionConfigMap.hasOwnProperty(item.fieldKey)) {
        conditionConfigMap[item.fieldKey].push(item);
      } else {
        conditionConfigMap[item.fieldKey] = [item];
      }
    });
  }
  switch (type) {
    case 'pie':
    case 'funnel':
      return pieChartDataSourceConvert(
        conditionDependencyMap,
        list,
        convert,
        conditionConfigMap,
        propsDefined,
        type,
      );
    case 'gauge':
      return gaugeChartDataSourceConvert(conditionDependencyMap, list, convert, conditionConfigMap, propsDefined);
    case 'word':
      return wordChartDataSourceConvert(conditionDependencyMap, list, convert, conditionConfigMap);
    case 'mix':
      return mixChartDataSourceConvert(conditionDependencyMap, list, convert, conditionConfigMap);
    default:
      return defaultChartDataSourceConvert(conditionDependencyMap, list, convert, conditionConfigMap);
  }
};

const defaultChartDataSourceConvert = (conditionDependencyMap, list, convert, conditionConfigMap) => {
  // 获取基础值
  const result = {
    categories: [],
    series: [],
  };
  // 如果传入值不可转换，返回
  if (!list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 遍历数据，开始转换
  list.forEach((item) => {
    // 仅在有类别时才进行转换，如果没有，省略该数据
    if (item[convert.categories]) {
      result.categories.push(item[convert.categories]);
      let categoriesStyle = '';
      conditionConfigMap[convert.categories] && conditionConfigMap[convert.categories].forEach((configItem) => {
        if (
            checkCondition(
                conditionDependencyMap,
                item[convert.categories],
                configItem.condition,
                configItem.type,
            )
        ) {
          categoriesStyle = configItem.style;
        }
      });
      if (convert.series && convert.series.length > 0) {
        convert.series.forEach((seriesItem, index) => {
          const seriesItemData = getSeriesItem(item[seriesItem.key]);
          let style = '';
          conditionConfigMap[seriesItem.key] &&
          conditionConfigMap[seriesItem.key].forEach((configItem) => {
            if (checkCondition(conditionDependencyMap, seriesItemData, configItem.condition, configItem.type)) {
              style = configItem.style;
            }
          });

          // 判断是否有样式，series优先级高于categories
          style = style ? style : categoriesStyle ? categoriesStyle : '';

          // 如果存在该配置项，推入数据信息
          if (result.series[index]) {
            result.series[index].data.push(
                style
                    ? {
                      value: seriesItemData,
                      color: style,
                    }
                    : seriesItemData,
            );
          } else {
            // 不存在初始化配置
            result.series[index] = {
              name: seriesItem.legend,
              data: [
                style
                    ? {
                      value: seriesItemData,
                      color: style,
                    }
                    : seriesItemData,
              ],
            };
          }
        });
      }
    }
  });
  return result;
};

// 仪表盘
const gaugeChartDataSourceConvert = (conditionDependencyMap, list, convert, conditionConfigMap, propsDefined) => {
  // 获取基础值
  const result = {
    categories: [
      { value: 0.2, color: '#1890ff' },
      { value: 0.8, color: '#2fc25b' },
      { value: 1, color: '#f04864' },
    ],
    series: [],
  };
  // 如果传入值不可转换，返回
  if (!list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 开始转换
  const listItem = list[0] || {};
  const seriesItemData = getSeriesItem(listItem[convert['data']]);
  // 设置主标题
  propsDefined['chartTitleName'] = seriesItemData;
  // 设置副标题
  propsDefined['chartSubTitleName'] = listItem[convert['name']];
  // 最小值
  const min = propsDefined['chartGaugeStartNumber'] || 0;
  // 最小值
  const max = propsDefined['chartGaugeEndNumber'] || 100;
  // 数值比例计算后的data值
  const gaugeData = (seriesItemData - min) / (max - min);
  let categoriesStyle = '';
  conditionConfigMap[convert['name']] && conditionConfigMap[convert['name']].forEach((configItem) => {
    if (
        checkCondition(
            conditionDependencyMap,
            listItem[convert['name']],
            configItem.condition,
            configItem.type,
        )
    ) {
      categoriesStyle = configItem.style;
    }
  });

  let style = '';
  conditionConfigMap[convert['data']] &&
    conditionConfigMap[convert['data']].forEach((configItem) => {
      if (checkCondition(conditionDependencyMap, seriesItemData, configItem.condition, configItem.type)) {
        style = configItem.style;
      }
    });
  // 判断是否有样式，series优先级高于categories
  style = style ? style : categoriesStyle ? categoriesStyle : '';
  result.series.push({
    name: listItem[convert['name']],
    data: gaugeData,
    titleColor: style,
  });
  return result;
};

const pieChartDataSourceConvert = (conditionDependencyMap, list, convert, conditionConfigMap, _propsDefined, chartType = 'pie') => {
  // 获取基础值
  const result = {
    series: [
      {
        data: [],
      },
    ],
  };
  // 如果传入值不可转换，返回
  if (!list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 遍历数据，开始转换
  list.forEach((item) => {
    let categoriesStyle = '';
    conditionConfigMap[convert.name] &&
    conditionConfigMap[convert.name].forEach((configItem) => {
      if (
          checkCondition(
              conditionDependencyMap,
              item[convert['name']],
              configItem.condition,
              configItem.type,
          )
      ) {
        categoriesStyle = configItem.style;
      }
    });
    // 仅在有类别时才进行转换，如果没有，省略该数据
    const seriesItemData = getSeriesItem(item[convert['value']]);
    let style = '';
    conditionConfigMap[convert['value']] &&
    conditionConfigMap[convert['value']].forEach((configItem) => {
      if (checkCondition(conditionDependencyMap, seriesItemData, configItem.condition, configItem.type)) {
        style = configItem.style;
      }
    });
    // 判断是否有样式，series优先级高于categories
    style = style ? style : categoriesStyle ? categoriesStyle : '';

    // 漏斗图条件配置修改扇形的颜色和label的文字颜色
    if (chartType === 'funnel') {
      result.series[0].data.push({
        name: item[convert['name']],
        value: seriesItemData,
        color: style,
        textColor: style,
      });
    } else {
      result.series[0].data.push({
        name: item[convert['name']],
        value: seriesItemData,
        color: style,
      });
    }
  });
  return result;
};

const wordChartDataSourceConvert = (conditionDependencyMap, list, convert, conditionConfigMap) => {
  // 获取基础值
  const result = {
    series: [],
  };
  // 如果传入值不可转换，返回
  if (!list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 遍历数据，开始转换
  list.forEach((item) => {
    const seriesItemData = getSeriesItem(item[convert['textSize']]);
    let categoriesStyle = '';
    conditionConfigMap[convert.name] &&
      conditionConfigMap[convert.name].forEach((configItem) => {
        if (
          checkCondition(
            conditionDependencyMap,
            item[convert['name']],
            configItem.condition,
            configItem.type,
          )
        ) {
          categoriesStyle = configItem.style;
        }
      });
    let style = '';
    conditionConfigMap[convert['textSize']] &&
      conditionConfigMap[convert['textSize']].forEach((configItem) => {
        if (
          checkCondition(
            conditionDependencyMap,
            seriesItemData,
            configItem.condition,
            configItem.type,
          )
        ) {
          style = configItem.style;
        }
      });
    // 判断是否有样式，series优先级高于categories
    style = style ? style : categoriesStyle ? categoriesStyle : '';
    result.series.push({
      name: item[convert['name']],
      textSize: seriesItemData,
      color: style,
    });
  });
  return result;
};

/**
 * 处理混合图的数据
 * @param listItem 每一项数据
 * @param source 数据转换源
 * @param conditionConfigMap 条件配置
 * @param categoriesStyle categories满足条件配置的样式
 * @param chartType 图表series中的type数据
 * @param chartStyle 图表series中的style数据
 * @param chartIndex 图表series中的index数据
 */
const handleMixChartSeriesData = ({
  listItem,
  source,
  conditionConfigMap,
  categoriesStyle,
  chartType,
  chartStyle = 'straight',
  chartIndex = 0,
  seriesData,
  conditionDependencyMap,
}) => {
  source.filter((item) => !isNullOrEmpty(item.key)).forEach((sourceItem, index) => {
    const sourceItemData = getSeriesItem(listItem[sourceItem.key]);
    let style = '';
    conditionConfigMap[sourceItem.key] &&
      conditionConfigMap[sourceItem.key].forEach((configItem) => {
        if (
          checkCondition(
            conditionDependencyMap,
            sourceItemData,
            configItem.condition,
            configItem.type,
          )
        ) {
          style = configItem.style;
        }
      });
    // 判断是否有样式，series优先级高于categories
    style = style ? style : categoriesStyle ? categoriesStyle : '';
    // 如果存在该配置项，推入数据信息
    if (seriesData[index]) {
      seriesData[index].data.push(
        style
          ? {
              value: sourceItemData,
              color: style,
            }
          : sourceItemData,
      );
    } else {
      // 不存在初始化配置
      seriesData[index] = {
        name: sourceItem.legend,
        index: chartIndex,
        type: chartType,
        style: chartStyle,
        data: [
          style
            ? {
                value: sourceItemData,
                color: style,
              }
            : sourceItemData,
        ],
      };
    }
  });
};
export const mixChartDataSourceConvert = (
  conditionDependencyMap,
  list,
  convert,
  conditionConfigMap,
) => {
  // 获取基础值
  const result = {
    categories: [],
    series: [],
  };
  const columnData = []; // 柱
  const surfaceData = []; // 曲面
  const curveData = []; // 曲线
  const lineData = []; // 折线
  const pointData = []; // 点
  // 如果传入值不可转换，返回
  if (!list || !isArray(list) || list.length === 0) {
    return list;
  }
  // 遍历数据，开始转换
  list.forEach((item) => {
    // 仅在有类别时才进行转换，如果没有，省略该数据
    if (item[convert.categories]) {
      result.categories.push(item[convert.categories]);
      let categoriesStyle = '';
      conditionConfigMap[convert.categories] &&
        conditionConfigMap[convert.categories].forEach((configItem) => {
          if (
            checkCondition(
              conditionDependencyMap,
              item[convert.categories],
              configItem.condition,
              configItem.type,
            )
          ) {
            categoriesStyle = configItem.style;
          }
        });
      // y-柱
      if (convert.column && convert.column.length > 0) {
        handleMixChartSeriesData({
          listItem: item,
          source: convert.column,
          conditionConfigMap,
          categoriesStyle,
          chartType: 'column',
          chartIndex: 1,
          seriesData: columnData,
          conditionDependencyMap,
        });
      }
      // y-曲面
      if (convert.surface && convert.surface.length > 0) {
        handleMixChartSeriesData({
          listItem: item,
          source: convert.surface,
          conditionConfigMap,
          categoriesStyle,
          chartType: 'area',
          chartStyle: 'curve',
          seriesData: surfaceData,
          conditionDependencyMap,
        });
      }
      // y-曲线
      if (convert.curve && convert.curve.length > 0) {
        handleMixChartSeriesData({
          listItem: item,
          source: convert.curve,
          conditionConfigMap,
          categoriesStyle,
          chartType: 'line',
          chartStyle: 'curve',
          seriesData: curveData,
          conditionDependencyMap,
        });
      }
      // y-折线
      if (convert.line && convert.line.length > 0) {
        handleMixChartSeriesData({
          listItem: item,
          source: convert.line,
          conditionConfigMap,
          categoriesStyle,
          chartType: 'line',
          seriesData: lineData,
          conditionDependencyMap,
        });
      }
      // y-点
      if (convert.point && convert.point.length > 0) {
        handleMixChartSeriesData({
          listItem: item,
          source: convert.point,
          conditionConfigMap,
          categoriesStyle,
          chartType: 'point',
          chartIndex: 2,
          seriesData: pointData,
          conditionDependencyMap,
        });
      }
    }
  });
  result.series.push(...pointData, ...lineData, ...curveData, ...surfaceData, ...columnData);
  return result;
};

// 获取配置的数据项，主要将非数字处理成数字
const getSeriesItem = (seriesStr) => {
  if (!seriesStr) {
    return 0;
  }
  const numArray = String(seriesStr).match(/-?\d+(.\d+)?/g);
  if (!numArray) {
    return 0;
  }
  if (isNaN(Number(numArray[0]))) {
    return 0;
  }
  return Number(numArray[0]);
};

// 校验是否满足该条件
const checkCondition = (conditionDependencyMap, currentData, condition, type) => {
  if (!condition || !condition.conditionType) {
    return false;
  }
  const { conditionType, conditionValue } = condition;
  let currentConditionValue = conditionDependencyMap.value[`_${conditionValue.id}`]();

  // 如果条件值不存在，则不满足条件
  if (
      currentConditionValue === undefined ||
      currentConditionValue === null ||
      currentData === undefined ||
      currentData === null
  ) {
    return false;
  }
  // 如果是number类型,传入的值无法转为数字
  if (type === 'NUMBER' && isNaN(Number(currentConditionValue))) {
    return false;
  }

  switch (conditionType) {
    case 'contain': // 包含
      return String(currentData).indexOf(currentConditionValue) > -1;
    case 'notContain': // 不包含
      return String(currentData).indexOf(currentConditionValue) === -1;
    case 'empty': // 为空
      return !currentData;
    case 'notEmpty': // 非空
      return !!currentData;
    case 'startWith': // 开头是
      return String(currentData).startsWith(currentConditionValue);
    case 'notStartWith': // 开头不是
      return !String(currentData).startsWith(currentConditionValue);
    case 'endWith': // 结尾是
      return String(currentData).endsWith(currentConditionValue);
    case 'notEndWith': // 结尾不是
      return !String(currentData).endsWith(currentConditionValue);
    case 'GT': // 大于
      return currentData > getSeriesItem(currentConditionValue);
    case 'LT': // 小于
      return currentData < getSeriesItem(currentConditionValue);
    case 'EQ': // 等于
      return currentData === getSeriesItem(currentConditionValue);
    case 'NE': // 不等于
      return currentData !== getSeriesItem(currentConditionValue);
    case 'GE': // 大于等于
      return currentData >= getSeriesItem(currentConditionValue);
    case 'LE': // 小于等于
      return currentData <= getSeriesItem(currentConditionValue);
    default:
      return false;
  }
};